define(function (require, exports, module) {
    var kity = require('./kity');
    var Minder = require('./minder');

    var protocols = {};

    function registerProtocol(name, protocol) {
        protocols[name] = protocol;

        for (var pname in protocols) {
            if (protocols.hasOwnProperty(pname)) {
                protocols[pname] = protocols[pname];
                protocols[pname].name = pname;
            }
        }
    }

    function getRegisterProtocol(name) {
        return name === undefined ? protocols : (protocols[name] || null);
    }

    exports.registerProtocol = registerProtocol;
    exports.getRegisterProtocol = getRegisterProtocol;

    // 导航图
    kity.extendClass(Minder, {

        /**
         * @method initNavbar()
         * @for Minder
         * @description
         *     初始化导航图
         */
        initNavbar: function () {
            /* 初始化显示导航图 */
            var renderTo = this._options.renderTo;
            var minder = this;

            $(renderTo).append('<div class="nav-bar">\n' +
                '                        <div class="nav-btn zoom-in" title="放大">\n' +
                '                            <div class="icon"></div>\n' +
                '                        </div>\n' +
                '                        <div class="zoom-pan">\n' +
                '                            <div class="origin"></div>\n' +
                '                            <div class="indicator" style="transition: transform 10ms;"></div>\n' +
                '                        </div>\n' +
                '                        <div class="nav-btn zoom-out" title="缩小">\n' +
                '                            <div class="icon"></div>\n' +
                '                        </div>\n' +
                '                        <div class="nav-btn hand" title="允许拖拽">\n' +
                '                            <div class="icon"></div>\n' +
                '                        </div>\n' +
                '                        <div class="nav-btn camera" title="定位根节点">\n' +
                '                            <div class="icon"></div>\n' +
                '                        </div>\n' +
                '                        <div class="nav-btn nav-trigger" title="导航器">\n' +
                '                            <div class="icon"></div>\n' +
                '                        </div>\n' +
                '                    </div>\n' +
                '                    <div class="nav-previewer" style="display: none;"></div>');

            var zoom = [10, 20, 30, 50, 80, 100, 120, 150, 200];
            minder.setDefaultOptions({ zoom: zoom });

            function getHeight(value) {
                var totalHeight = $(renderTo + ' .zoom-pan').height();

                var zoomStack = minder.getOption('zoom');
                var minValue = zoomStack[0];
                var maxValue = zoomStack[zoomStack.length - 1];
                var valueRange = maxValue - minValue;

                return totalHeight * (1 - (value - minValue) / valueRange);
            }

            $(renderTo + " .indicator").css("transform", "translate(0," + getHeight(100) + "px)");
            $(renderTo + " .origin").css("transform", "translate(0," + getHeight(100) + "px)");
            minder.on('zoom', function (e) {
                var r = getHeight(e.zoom);
                $(renderTo + " .indicator").css("transform", "translate(0," + r + "px)");
            });

            /** 以下部分是缩略图导航器 **/

            var $previewNavigator = $(renderTo + ' .nav-previewer');

            // 画布，渲染缩略图
            var paper = new kity.Paper($previewNavigator[0]);

            // 用两个路径来挥之节点和连线的缩略图
            var nodeThumb = paper.put(new kity.Path());
            var connectionThumb = paper.put(new kity.Path());

            // 表示可视区域的矩形
            var visibleRect = paper.put(new kity.Rect(100, 100).stroke('#6666CC', '1%'));

            var contentView = new kity.Box(), visibleView = new kity.Box();


            /**
             *
             * 缩略图
             * */
            var pathHandler = getPathHandler(minder.getTheme());

            function getPathHandler(theme) {
                return function (nodePathData, x, y, width, height) {
                    nodePathData.push('M', x, y,
                        'h', width, 'v', height,
                        'h', -width, 'z');
                }
            }

            navigate();

            function navigate() {

                function moveView(center, duration) {
                    var box = visibleView;
                    center.x = -center.x;
                    center.y = -center.y;

                    var viewMatrix = minder.getPaper().getViewPortMatrix();
                    box = viewMatrix.transformBox(box);

                    var targetPosition = center.offset(box.width / 2, box.height / 2);

                    minder.getViewDragger().moveTo(targetPosition, duration);
                }

                var dragging = false;

                paper.on('mousedown', function (e) {
                    dragging = true;
                    moveView(e.getPosition('top'), 200);
                    $previewNavigator.addClass('grab');
                });

                paper.on('mousemove', function (e) {
                    if (dragging) {
                        moveView(e.getPosition('top'));
                    }
                });

                $(window).on('mouseup', function () {
                    dragging = false;
                    $previewNavigator.removeClass('grab');
                });
            }

            function updateContentView() {
                var view = minder.getRenderContainer().getBoundaryBox();

                contentView = view;

                var padding = 30;

                paper.setViewBox(
                    view.x - padding - 0.5,
                    view.y - padding - 0.5,
                    view.width + padding * 2 + 1,
                    view.height + padding * 2 + 1);

                var nodePathData = [];
                var connectionThumbData = [];

                minder.getRoot().traverse(function (node) {
                    var box = node.getLayoutBox();
                    pathHandler(nodePathData, box.x, box.y, box.width, box.height);
                    if (node.getConnection() && node.parent && node.parent.isExpanded()) {
                        connectionThumbData.push(node.getConnection().getPathData());
                    }
                });

                paper.setStyle('background', minder.getStyle('background'));

                if (nodePathData.length) {
                    nodeThumb
                        .fill(minder.getStyle('root-background'))
                        .setPathData(nodePathData);
                } else {
                    nodeThumb.setPathData(null);
                }

                if (connectionThumbData.length) {
                    connectionThumb
                        .stroke(minder.getStyle('connect-color'), '0.5%')
                        .setPathData(connectionThumbData);
                } else {
                    connectionThumb.setPathData(null);
                }

                updateVisibleView();
            }

            function updateVisibleView() {
                visibleView = minder.getViewDragger().getView();
                visibleRect.setBox(visibleView.intersect(contentView));
            }

            // 放大
            $(renderTo + " .zoom-in").click(function () {
                minder.execCommand("zoomIn");
            });
            // 缩小
            $(renderTo + " .zoom-out").click(function () {
                minder.execCommand("zoomOut");
            });
            // 允许拖拽
            $(renderTo + " .hand").click(function () {
                var r = minder.execCommand('hand');
                $(renderTo + " .hand").toggleClass("active");
            });
            // 定位根节点
            $(renderTo + " .camera").click(function () {
                minder.execCommand('camera', minder.getRoot(), 600);
            });
            // 导航器
            $(renderTo + " .nav-trigger").click(function () {
                $(renderTo + " .nav-previewer").toggle();
                $(renderTo + " .nav-trigger").toggleClass("active");
                if (true === $(renderTo + " .nav-previewer").is(":visible")) {
                    bind();
                    updateContentView();
                    updateVisibleView();
                } else {
                    unbind();
                }
            });

            function bind() {
                minder.on('layout layoutallfinish', updateContentView);
                minder.on('viewchange', updateVisibleView);
            }

            function unbind() {
                minder.off('layout layoutallfinish', updateContentView);
                minder.off('viewchange', updateVisibleView);
            }
        }
    });
});